
module dares.Types ;

public import
	
	dares.Ares,
	dares.Dns,
	dares.Llist,
	dares.Private,

	tango.core.Array ,
	tango.core.Traits,

	tango.io.Stdout,
	tango.io.device.Array ,
	tango.io.device.File ,

	tango.net.device.Berkeley,

	Int	= tango.text.convert.Integer ,

	tango.stdc.time,
	tango.stdc.stringz,
	
	tango.sys.win32.consts.socket,
	tango.sys.win32.WsaSock ,
	tango.sys.win32.UserGdi ;

alias int		c_int ;
alias ushort	c_ushort ;
alias int		c_long ;


alias int		ares_socket_t ;
alias int		ares_socklen_t ;
alias tango.net.device.Berkeley.SocketSet.fd		fd_set ;

alias tango.net.device.Berkeley.SocketSet.timeval	timeval ;

struct sockaddr ;

extern(C){
	void exit(int);
	void printf(char*,...);
	int memcpy(void* dst, void* src, int len);
	int ares_inet_pton(c_int af, char* src,void* dst);
	timeval* ares_timeout(ares_channel channel, timeval *maxtv, timeval *tvbuf);
}

char* toStringz(char[] name){
	char[] name_	= new char[ name.length+1] ;
	foreach(int i, c;name) name_[i] = c;
	name_[$-1]	= 0 ;
	return name_.ptr ;
}

struct _Struct {
	struct _Field {
		int		_index ;
		int		_size	;
		int		_offset ;
		char[]	_name ;
	}
	char[]	_name ;
	int		_size	;
	int		_len	;
	_Field*[]	_fields ;
	
	static _Struct*[]	 list ;
	
	static void Load(alias S)(char[][] _exclude = null){
		_Struct* p	= new _Struct ;
		p._name	= S.stringof ;
		p._size	= S.sizeof ;
		int	idx	= 0 ;
		foreach(int i, c ; S.init.tupleof) {
			_Field* _p	= new _Field ;
			_p._name	= S.tupleof[i].stringof[ S.stringof.length + 3 ..$] ;
			bool	v	= true ;
			if( _p._name.length > 2 && _p._name[0] is '_' && _p._name[1] is '_' ){
				v	= false ;
			}else if( _exclude !is null ) {
				if( contains( _exclude , _p._name) ){
					v	= false ;
				}
			}
			_p._size	= c.sizeof ;
			_p._offset	= S.tupleof[i]. offsetof ;
			_p._index	=  v ? idx++ : -1 ;
			p._fields	~= _p ;
		}
		p._len	= idx ;
		list		~= p	;
	}
	
	static void Dump(){
		foreach( s ; list ){
			Stdout.formatln("{}	{}", s._name, s._size );
			foreach( f; s._fields ){
				Stdout.formatln("	{}	{}	{}	{}",	f._name, f._offset, f._size, f._index );
			}
		}
	}
	
	static void GenTest(){
		auto bu	= new Array(1024, 1024) ;
		auto b2	= new Array(1024, 1024) ;
		bu( File.get(`test_header.txt`) ) ;
		bu( File.get(`test_struct_start.txt`) ) ;
		int	_len1	= bu.slice.length ;
		b2("void _d_struct_dump(){\n\tstruct _d_struct	*s ;\n\tstruct _d_field	*f , *_f ;\n\tfor(int i = 0; i < _struct_len;i++) {\n");
		int	_len	= 0 ;
		foreach( s ; list ){
			_len++;
			GenStructTest(s, bu, b2);
		}
		space( bu );
		space( b2 );
		bu("};\n");
		bu("\nint _struct_len = ")( Int.toString(_len) ) (" ;\n");
		b2("\t};\n}\n");
		
		bu( b2.slice );
		
		int	_len2	= bu.slice.length ;
		bu( File.get(`test_struct_end.txt`) )("\n");
		File.set(`../test.c`, bu.slice );
		
		return ;
		char[] _da	= cast(char[]) bu.slice  ;
		_da[_len2]	= 0 ;
		printf("%s", &_da[_len1]);
	}
	
	static void GenStructTest(_Struct* s, Array bu, Array b2){
		bu("\t{\"")(s._name)("\", ")( Int.toString(s._size) )(", sizeof(struct ")(s._name)("), ")( Int.toString(s._len ) ) ;
		
		if( s._len > 0 ){
			b2("\t\ts	= &_struct_list[i];\n");
			foreach( f ; s._fields ) if( f._index>= 0 ){
				b2("\t\t\tf	= malloc( sizeof(struct _d_field)  ) ;\n");
				b2("\t\t\tmemset(f, 0, sizeof(struct _d_field)  );\n");
				
				if( f._index is 0 ){
					b2("\t\t\ts->list	= f ;\n");
				}else{
					b2("\t\t\t_f->next	= f ;\n");
				}
				b2("\t\t\tf->name	= \"")( f._name )("\" ;\n");
				b2("\t\t\tf->_off	= ")( Int.toString(f._offset) )(" ;\n");
				b2("\t\t\tf->_size	= ")( Int.toString(f._size) )(" ;\n");
				b2("\t\t\tf->off		= offsetof(struct ")(s._name)(", ")(f._name)(") ;\n");
				b2("\t\t\tf->size		= FSIZ(struct ")(s._name)(", ")(f._name)(") ;\n");
				b2("\t\t\t_f = f ;\n");
			}
		}
		bu("},\n");
	}
	
	static void space(Array bu){
		if( bu is null ||  bu.slice .length is 0 ) return ;
		char* _p	= cast(char*) &( bu.slice )[ 0 ] ;
		char* p	= cast(char*) &( bu.slice )[ $ - 1 ] ;
		
		while(  p > _p ){
			if( *p is '\n' || *p is '\r' || *p is '\t' || *p is ' ' ){
				p-- ;
			}else{
				break ;
			}
		}
		
		if( *p is ',' ){
			*p	= ' ' ;
		}
		
	}
}
